using System;
using System.Threading;

namespace HF.Repository
{  
    public delegate bool CacheGetter<TData>(out TData data);

    public static class CacheHelper
    {
        #region Delegates

      
        #endregion

        public static TData Get<TData>(
            CacheGetter<TData> cacheGetter,
            Func<TData> sourceGetter,
            Action<TData> cacheSetter)
        {
            TData data;
            if (cacheGetter(out data))
            {
                return data;
            }

            data = sourceGetter();
            cacheSetter(data);

            return data;
        }

        public static TData Get<TData>(
            CacheGetter<TData> cacheGetter,
            Func<TData> sourceGetter,
            Action<TData> cacheSetter, ReaderWriterLockSlim rwlock)
        {
            TData data;
            rwlock.EnterReadLock();
            bool cacheHit = cacheGetter(out data);
            rwlock.ExitReadLock();

            if (cacheHit) return data;

            rwlock.EnterWriteLock();
            if (!cacheGetter(out data))
            {
                try
                {
                    data = sourceGetter();
                    cacheSetter(data);
                }
                finally
                {
                    rwlock.ExitWriteLock();
                }
            }
            return data;
        }
    }
}